// 
// Bachelor of Software Engineering
// Media Design School
// Auckland
// New Zealand
//
// (c) 2005 - 2014 Media Design School
//
// File Name	: SpaceInvadersHumanView.cpp
// Desrciption	: CSpaceInvadersHumanView implementation file.
// Author		: Hayden Asplet.
// Mail			: hayden.asplet@mediadesignschool.com
//

// PCH
#include "SpaceInvadersStd.h"

// Library Includes

// This Include
#include "SpaceInvadersHumanView.h"

// Local Includes
#include "Msvc\resource.h"
#include "SpaceInvadersLogic.h"
#include "SpaceInvadersObjectComponents\CannonComponent.h"

CSpaceInvadersHumanView::CSpaceInvadersHumanView()
{

#ifdef _DEBUG
	m_hDebugDlg = CreateDialog(g_pApp->GetInstance(), 
							   MAKEINTRESOURCE(IDD_DEBUG), 
							   g_pApp->GetHwnd(), 
							   CSpaceInvadersHumanView::DialogProc);
#endif
}

CSpaceInvadersHumanView::~CSpaceInvadersHumanView()
{

}

void CSpaceInvadersHumanView::VUpdate(float _fDeltaTime)
{
	// Retrieve the attached object.
	CGameObject* pAttachedObject = g_pApp->m_pGame->GetGameObject(m_objectId);

	if(!pAttachedObject) {
	// Couldn't retrieve attached object.
		return;
	}

	shared_ptr<CPhysicsComponent> pPhysicsComponent = pAttachedObject->GetComponent<CPhysicsComponent>();
	shared_ptr<CAnimationComponent> pAnimComponent = pAttachedObject->GetComponent<CAnimationComponent>();

	if(pAnimComponent) {
		if(pAnimComponent->GetCurrentAnimation() == "Death") {
			// Stop the physics of the cannon.
			pPhysicsComponent->Stop();

			// return.
			return;
		}
	}

	if(m_bKeys[VK_SPACE]) {
	// Player wants to fire a bullet.
		shared_ptr<CCannonComponent> pCannonComponent = pAttachedObject->GetComponent<CCannonComponent>();

		if(pCannonComponent) {
			// Fire a bullet.
			pCannonComponent->FireBullet();
		}
	}

	shared_ptr<CEvtDataMoveObject> pEvent;		// The event to trigger.

	if(m_bKeys[VK_RIGHT] && !m_bKeys[VK_LEFT]) {
	// The player wants to move right.
		pEvent.reset(new CEvtDataMoveObject(m_objectId, true, g_kfCANNON_ACCELERATION, g_kfCANNON_MAX_VELOCITY));
		CEventManager::GetInstance()->QueueEvent(pEvent);
	}
	else if(m_bKeys[VK_LEFT] && !m_bKeys[VK_RIGHT]) {
	// The player wants to move left.
		pEvent.reset(new CEvtDataMoveObject(m_objectId, true, -g_kfCANNON_ACCELERATION, g_kfCANNON_MAX_VELOCITY));
		CEventManager::GetInstance()->QueueEvent(pEvent);
	}
	else {
		// Stop the cannon by deccelerating it.
		if(pPhysicsComponent->GetVelocityX() > 0) {
			pEvent.reset(new CEvtDataMoveObject(m_objectId, true, -g_kfCANNON_ACCELERATION, 0));
			CEventManager::GetInstance()->QueueEvent(pEvent);
		}
		else if(pPhysicsComponent->GetVelocityX() < 0) {
			pEvent.reset(new CEvtDataMoveObject(m_objectId, true, g_kfCANNON_ACCELERATION, 0));
			CEventManager::GetInstance()->QueueEvent(pEvent);
		}
	}
}

void CSpaceInvadersHumanView::VRender(float _fDeltaTime)
{
	CRenderer* pRenderer = g_pApp->m_pGame->GetRenderer();

	if(pRenderer) {
		pRenderer->RenderGameObjects();
	}

	int iScore = 0;
	int iLives = 0;

	CGameObject* pAttachedObject = g_pApp->m_pGame->GetGameObject(m_objectId);

	if(pAttachedObject) {
		shared_ptr<CCannonComponent> pCannonComponent = pAttachedObject->GetComponent<CCannonComponent>();

		if(pCannonComponent) {
			// Retrieve the score and lives of the cannon.
			iScore = pCannonComponent->GetScore();
			iLives = pCannonComponent->GetLives();
		}
	}

	// Display the score and lives to the screen.
	std::string strTextOut = "Score: " + std::to_string(static_cast<long long>(iScore));
	strTextOut += "    Lives: " + std::to_string(static_cast<long long>(iLives));

	g_pApp->RenderText(strTextOut,									   // The text.
					   g_kiSTANDARD_UI_OFFSET, g_kiSTANDARD_UI_OFFSET, // Position.
					   g_kWHITE,									   // Colour.
					   g_kiSTANDARD_TEXT_HEIGHT,					   // Text height.
					   "HaxrCorp S8");								   // Font.
}

bool CSpaceInvadersHumanView::VMsgProc(const CAppMsg& _krMsg)
{
	switch(_krMsg.m_uMsg) {
		case WM_KEYDOWN: {
#ifdef _DEBUG
			if(_krMsg.m_wParam == VK_ESCAPE) {
				ShowWindow(m_hDebugDlg, SW_SHOW);

				CGameObject* pAttachedObject = g_pApp->m_pGame->GetGameObject(m_objectId);

				if(pAttachedObject) {
					shared_ptr<CCannonComponent> pCannonComponent = pAttachedObject->GetComponent<CCannonComponent>();

					if(pCannonComponent) {
						// Retrieve the score and lives of the cannon.
						int iScore = pCannonComponent->GetScore();
						int iLives = pCannonComponent->GetLives();

						std::wstring wsScore = std::to_wstring(static_cast<long long>(iScore));
						std::wstring wsLives = std::to_wstring(static_cast<long long>(iLives));

						SetDlgItemText(m_hDebugDlg, IDC_SCORE, wsScore.c_str());
						SetDlgItemText(m_hDebugDlg, IDC_LIVES, wsLives.c_str());
					}
				}

				return true;
			}
#endif
			break;
		}
		case WM_KEYUP: {
			break;
		}
		case WM_MOUSEMOVE: {

			break;
		}
		case WM_LBUTTONDOWN: {

			break;
		}
		case WM_LBUTTONUP: {

			break;
		}
		case WM_RBUTTONDOWN: {

			break;
		}
		case WM_RBUTTONUP: {

			break;
		}
		default: break;
	}

	return CHumanView::VMsgProc(_krMsg);
}

BOOL CALLBACK CSpaceInvadersHumanView::DialogProc(HWND _hDlg, UINT _uMsg, WPARAM _wParam, LPARAM _lParam)
{
	switch(_uMsg) {
		case WM_INITDIALOG:
		{
			// Do initialization stuff here...

			// Return success.
			return true;
		}
		break;
		case WM_COMMAND: {
			switch(LOWORD(_wParam)) {
				case IDOK: {
					if(IsDlgButtonChecked(_hDlg, IDC_FRAME_RATE)) {
						g_pApp->SetFrameRateShowing(true);
					}
					else {
						g_pApp->SetFrameRateShowing(false);
					}

					// Get the space invaders logic.
					CSpaceInvadersLogic* pGame = dynamic_cast<CSpaceInvadersLogic*>(g_pApp->m_pGame);

					if(pGame) {
						shared_ptr<CCannonComponent> pCannonComponent = pGame->GetCannonComponent();

						if(pCannonComponent) {
							if(IsDlgButtonChecked(_hDlg, IDC_INVULNERABLE)) {
								pCannonComponent->SetInvulnerability(true);
							}
							else {
								pCannonComponent->SetInvulnerability(false);
							}

							if(IsDlgButtonChecked(_hDlg, IDC_RAPID_FIRE)) {
								pCannonComponent->SetAmmo(50);
							}
							else {
								pCannonComponent->SetAmmo(1);
							}

							wchar_t text[32];

							// Get the lives.
							GetDlgItemText(_hDlg, IDC_LIVES, text, 32);
							pCannonComponent->SetLives(static_cast<int>(_wtoi(text)));

							// Get the score.
							GetDlgItemText(_hDlg, IDC_SCORE, text, 32);
							pCannonComponent->SetScore(static_cast<int>(_wtoi(text)));
						}
					}

					ShowWindow(_hDlg, SW_HIDE);

					return true;
				}
				break;
			}
			return true;
		}
		case WM_DESTROY: {
			// Kill the application, this sends a WM_QUIT message.
			ShowWindow(_hDlg, SW_HIDE);

			// Return Success.
			return true;
		}
		break;
		case WM_CLOSE: {
			// Kill the application, this sends a WM_QUIT message.
			ShowWindow(_hDlg, SW_HIDE);

			// Return Success.
			return true;
		}
		default:break;
	} // End switch.

	return false;
}
